package com.horay.nettydemo.bio.server;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Objects;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * BIO服务器
 * 测试：
 *     cmd -> telnet 127.0.0.1 6666
 *     CTRL+] -> send <字符串>
 *
 * @author heyingcheng
 * @date 2019/11/23 12:31
 */
@Slf4j
public class BioServer {

    private int port;

    private volatile boolean running = true;

    private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(0, 10, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());

    public BioServer(int port) {
        this.port = port;
    }

    public void start() {
        try (ServerSocket serverSocket = new ServerSocket(port)) {
            log.info("服务器启动完成");
            while (running) {
                log.info("服务器接受客户端");
                Socket socket = serverSocket.accept();
                THREAD_POOL_EXECUTOR.execute(() -> {
                    socketHandler(socket);
                });
            }
        } catch (IOException e) {
            log.error("服务器启动异常", e);
        }
    }

    private void socketHandler(Socket socket) {
        byte[] bytes = new byte[1024];
        try (InputStream inputStream = socket.getInputStream()) {
            while(true) {
                int read = inputStream.read(bytes);
                if (read != -1) {
                    String message = new String(bytes, 0, read);
                    log.info("服务器收到消息:[{}]", message);
                }
            }
        } catch (IOException e) {
            log.error("服务器读取消息异常", e);
        } finally {
            try {
                if (Objects.nonNull(socket)) {
                    socket.close();
                }
            } catch (IOException e) {
                log.error("客户端关闭异常", e);
            }
        }
    }

    public void stop() {
        this.running = false;
        THREAD_POOL_EXECUTOR.shutdown();
    }
    
}
